import conf.settings as settings
from metric_reader import MetricReader
from lib.metric_type.capacity import CapacityMetric, Level
from lib.metric_exception import MetricSettingsException,\
    MetricCollectException, MetricProcessException

MOUNTPOINT = "/"
NODE_LABEL = settings.NODE_LABEL


# node roootfs util = (100 - f_bavail/(f_blokcs - f_bfree + f_bavail) * 100)
class NodeRootfsUtil(CapacityMetric):
    def __init__(self, metric_reader: MetricReader,
                 metric_settings, level: Level):
        super().__init__(metric_reader, metric_settings, level)

    def _collect_process_metric(self):
        metric_name = self.settings.collect.metric_name
        node_tag = self.settings.collect.node_tag_name

        if self.level != Level.Node:
            raise MetricSettingsException(
                f"{self.settings.collect.metric_name} is a "
                f"node level metric!"
            )

        avail_value = self.settings.collect.related_value[0]
        blocks_value = self.settings.collect.related_value[1]
        bfree_balue = self.settings.collect.related_value[2]
        query_args = {
            NODE_LABEL: self.name[Level.Node],
            node_tag: avail_value,
            "mount": MOUNTPOINT
        }

        bavail_res = self._get_custom_metric(metric_name,
                                             **query_args)

        query_args[node_tag] = blocks_value
        blocks_res = self._get_custom_metric(metric_name,
                                             **query_args)

        query_args[node_tag] = bfree_balue
        bfree_res = self._get_custom_metric(metric_name,
                                            **query_args)

        # 因为是节点指标，查询出来的data应该只有1个
        if not (len(bavail_res.data) == len(blocks_res.data)
                == len(bfree_res.data) == 1):
            raise MetricCollectException(
                f"Collect {metric_name},"
                " Level: {self.level} from Prometheus failed!"
            )

        try:
            # 都取区间向量中点的最大值
            max_bavail = max(
                [float(item[1])
                 for item in bavail_res.data[0].to_dict()["values"]]
            )
            max_blocks = max(
                [float(item[1])
                 for item in blocks_res.data[0].to_dict()["values"]]
            )
            max_bfree = max(
                [float(item[1])
                 for item in bfree_res.data[0].to_dict()["values"]]
            )
            final_value = (100 - max_bavail / (max_blocks -
                           max_bfree + max_bavail) * 100)

        except Exception as exc:
            raise MetricProcessException from exc

        return final_value
